﻿using System;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;

namespace BepuUtilities.Vectors
{

    public struct Vector<T> : IEquatable<Vector<T>>, IFormattable where T : struct
	{
		private static int count;

		public static int Count
		{
			
			get
			{
				//ThrowHelper.ThrowForUnsupportedVectorBaseType<T>();
				//if (count == 0)
				//	count= Unsafe.SizeOf<Vector<T>>() / Unsafe.SizeOf<T>();
				//return count;
				return 4;
			}
		}

		public static Vector<T> Zero
		{
			
			get
			{
				return Vector<T>.s_zero;
			}
		}

		public static Vector<T> One
		{
			
			get
			{
				return Vector<T>.s_one;
			}
		}

		internal static Vector<T> AllOnes
		{
			
			get
			{
				return Vector<T>.s_allOnes;
			}
		}

		
		public unsafe Vector(T value)
		{
			this = default(Vector<T>);
			if (Vector.IsHardwareAccelerated)
			{
				
				if (typeof(T) == typeof(int))
				{
					fixed (int* ptr11 = &this.register.int32_0)
					{
						int* ptr12 = ptr11;
						for (int n = 0; n < Vector<T>.Count; n++)
						{
							ptr12[n] = (int)((object)value);
						}
					}
					return;
				}
				
				if (typeof(T) == typeof(float))
				{
					fixed (float* ptr17 = &this.register.single_0)
					{
						float* ptr18 = ptr17;
						for (int num3 = 0; num3 < Vector<T>.Count; num3++)
						{
							ptr18[num3] = (float)((object)value);
						}
					}
					return;
				}
				
			}
			else
			{
				
				if (typeof(T) == typeof(int))
				{
					this.register.int32_0 = (int)((object)value);
					this.register.int32_1 = (int)((object)value);
					this.register.int32_2 = (int)((object)value);
					this.register.int32_3 = (int)((object)value);
					return;
				}
				
				if (typeof(T) == typeof(float))
				{
					this.register.single_0 = (float)((object)value);
					this.register.single_1 = (float)((object)value);
					this.register.single_2 = (float)((object)value);
					this.register.single_3 = (float)((object)value);
					return;
				}
			}
		}

		
		public Vector(T[] values)
		{
			this = new Vector<T>(values, 0);
		}

		
		public unsafe Vector(T[] values, int index)
		{
			this = default(Vector<T>);
			if (values == null)
			{
				throw new NullReferenceException();
			}
			if (index < 0 || values.Length - index < Vector<T>.Count)
			{
				throw new IndexOutOfRangeException();
			}
			if (Vector.IsHardwareAccelerated)
			{
				
				if (typeof(T) == typeof(int))
				{
					fixed (int* ptr11 = &this.register.int32_0)
					{
						int* ptr12 = ptr11;
						for (int n = 0; n < Vector<T>.Count; n++)
						{
							ptr12[n] = (int)((object)values[n + index]);
						}
					}
					return;
				}
				
				if (typeof(T) == typeof(float))
				{
					fixed (float* ptr17 = &this.register.single_0)
					{
						float* ptr18 = ptr17;
						for (int num3 = 0; num3 < Vector<T>.Count; num3++)
						{
							ptr18[num3] = (float)((object)values[num3 + index]);
						}
					}
					return;
				}
			}
			else
			{
				
				if (typeof(T) == typeof(int))
				{
					fixed (int* ptr31 = &this.register.int32_0)
					{
						int* ptr32 = ptr31;
						*ptr32 = (int)((object)values[index]);
						ptr32[1] = (int)((object)values[1 + index]);
						ptr32[2] = (int)((object)values[2 + index]);
						ptr32[3] = (int)((object)values[3 + index]);
					}
					return;
				}
				
				if (typeof(T) == typeof(float))
				{
					fixed (float* ptr37 = &this.register.single_0)
					{
						float* ptr38 = ptr37;
						*ptr38 = (float)((object)values[index]);
						ptr38[1] = (float)((object)values[1 + index]);
						ptr38[2] = (float)((object)values[2 + index]);
						ptr38[3] = (float)((object)values[3 + index]);
					}
					return;
				}
				
			}
		}

		internal unsafe Vector(void* dataPointer)
		{
			this = new Vector<T>(dataPointer, 0);
		}

		internal unsafe Vector(void* dataPointer, int offset)
		{
			this = default(Vector<T>);
			
			if (typeof(T) == typeof(int))
			{
				int* ptr16 = (int*)((byte*)dataPointer + (offset * 4));
				fixed (int* ptr17 = &this.register.int32_0)
				{
					int* ptr18 = ptr17;
					for (int n = 0; n < Vector<T>.Count; n++)
					{
						ptr18[n] = ptr16[n];
					}
				}
				return;
			}
			
			if (typeof(T) == typeof(float))
			{
				float* ptr25 = (float*)((byte*)dataPointer + (offset * 4));
				fixed (float* ptr26 = &this.register.single_0)
				{
					float* ptr27 = ptr26;
					for (int num3 = 0; num3 < Vector<T>.Count; num3++)
					{
						ptr27[num3] = ptr25[num3];
					}
				}
				return;
			}
			throw new NotSupportedException();
		}

		private Vector(ref Register existingRegister)
		{
			this.register = existingRegister;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Vector(ReadOnlySpan<byte> values)
		{
			this = default(Vector<T>);
			//ThrowHelper.ThrowForUnsupportedVectorBaseType<T>();
			if (values.Length < Vector<byte>.Count)
			{
				Vector.ThrowInsufficientNumberOfElementsException(Vector<byte>.Count);
			}
			this = Unsafe.ReadUnaligned<Vector<T>>(ref MemoryMarshal.GetReference<byte>(values));
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Vector(ReadOnlySpan<T> values)
		{
			this = default(Vector<T>);
			if (values.Length < Vector<T>.Count)
			{
				Vector.ThrowInsufficientNumberOfElementsException(Vector<T>.Count);
			}
			this = Unsafe.ReadUnaligned<Vector<T>>(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference<T>(values)));
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public Vector(Span<T> values)
		{
			this = default(Vector<T>);
			if (values.Length < Vector<T>.Count)
			{
				Vector.ThrowInsufficientNumberOfElementsException(Vector<T>.Count);
			}
			this = Unsafe.ReadUnaligned<Vector<T>>(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference<T>(values)));
		}

		public readonly void CopyTo(Span<byte> destination)
		{
			//ThrowHelper.ThrowForUnsupportedVectorBaseType<T>();
			if (destination.Length < Vector<byte>.Count)
			{
				//ThrowHelper.ThrowArgumentException_DestinationTooShort();
			}
			Unsafe.WriteUnaligned<Vector<T>>(ref MemoryMarshal.GetReference<byte>(destination), this);
		}

		public readonly void CopyTo(Span<T> destination)
		{
			if (destination.Length < Vector<T>.Count)
			{
				//ThrowHelper.ThrowArgumentException_DestinationTooShort();
			}
			Unsafe.WriteUnaligned<Vector<T>>(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference<T>(destination)), this);
		}

		
		public readonly void CopyTo(T[] destination)
		{
			this.CopyTo(destination, 0);
		}

		
		public unsafe readonly void CopyTo( T[] destination, int startIndex)
		{
			if (destination == null)
			{
				throw new NullReferenceException();
			}
			if (startIndex < 0 || startIndex >= destination.Length)
			{
				throw new ArgumentOutOfRangeException();
			}
			if (destination.Length - startIndex < Vector<T>.Count)
			{
				throw new ArgumentException();
			}
			if (Vector.IsHardwareAccelerated)
			{
				if (typeof(T) == typeof(int))
				{
                    int[] array11 = destination as int[];
					int[] array12;
					int* ptr6;
					if ((array12 = array11) == null || array12.Length == 0)
					{
						ptr6 = null;
					}
					else
					{
						fixed(int* ptr2 = &array12[0])
							ptr6 = ptr2;
					}
					for (int n = 0; n < Vector<T>.Count; n++)
					{
						ptr6[startIndex + n] = (int)((object)this[n]);
					}
					array12 = null;
					return;
				}
				if (typeof(T) == typeof(float))
				{
					float[] array17 = destination as float[];
					float[] array18;
					float* ptr9;
					if ((array18 = array17) == null || array18.Length == 0)
					{
						ptr9 = null;
					}
					else
					{
						fixed (float* ptr2 = &array18[0])
							ptr9 = ptr2;
					}
					for (int num3 = 0; num3 < Vector<T>.Count; num3++)
					{
						ptr9[startIndex + num3] = (float)((object)this[num3]);
					}
					array18 = null;
					return;
				}
			}
			else
			{
				if (typeof(T) == typeof(int))
				{
					int[] array26 = destination as int[];
					int[] array12;
					int* ptr16;
					if ((array12 = array26) == null || array12.Length == 0)
					{
						ptr16 = null;
					}
					else
					{
						fixed (int* ptr2 = &array12[0])
							ptr16 = ptr2;
					}
					ptr16[startIndex] = this.register.int32_0;
					ptr16[startIndex + 1] = this.register.int32_1;
					ptr16[startIndex + 2] = this.register.int32_2;
					ptr16[startIndex + 3] = this.register.int32_3;
					array12 = null;
					return;
				}
				if (typeof(T) == typeof(float))
				{
					float[] array29 = destination as float[];
					float[] array18;
					float* ptr19;
					if ((array18 = array29) == null || array18.Length == 0)
					{
						ptr19 = null;
					}
					else
					{
						fixed (float* ptr2 = &array18[0])
							ptr19 = ptr2;
					}
					ptr19[startIndex] = this.register.single_0;
					ptr19[startIndex + 1] = this.register.single_1;
					ptr19[startIndex + 2] = this.register.single_2;
					ptr19[startIndex + 3] = this.register.single_3;
					array18 = null;
					return;
				}
				
			}
		}

		public unsafe readonly T this[int index]
		{
			
			get
			{
				if (index >= Count || index < 0)
				{
					throw new IndexOutOfRangeException();
				}
				
				if (typeof(T) == typeof(int))
				{
					fixed (int* ptr11 = &this.register.int32_0)
					{
						int* ptr12 = ptr11;
						return (T)((object)ptr12[index]);
					}
				}
				
				if (typeof(T) == typeof(float))
				{
					fixed (float* ptr17 = &this.register.single_0)
					{
						float* ptr18 = ptr17;
						return (T)((object)ptr18[index]);
					}
				}
				
				throw new NotSupportedException();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public override readonly bool Equals(object obj)
		{
			return obj is Vector<T> && this.Equals((Vector<T>)obj);
		}

		
		public readonly bool Equals(Vector<T> other)
		{
			if (Vector.IsHardwareAccelerated)
			{
				for (int i = 0; i < Vector<T>.Count; i++)
				{
					if (!Vector<T>.ScalarEquals(this[i], other[i]))
					{
						return false;
					}
				}
				return true;
			}
			
			if (typeof(T) == typeof(int))
			{
				return this.register.int32_0 == other.register.int32_0 && this.register.int32_1 == other.register.int32_1 && this.register.int32_2 == other.register.int32_2 && this.register.int32_3 == other.register.int32_3;
			}
			
			if (typeof(T) == typeof(float))
			{
				return this.register.single_0 == other.register.single_0 && this.register.single_1 == other.register.single_1 && this.register.single_2 == other.register.single_2 && this.register.single_3 == other.register.single_3;
			}
			
			throw new NotSupportedException();
		}

		public override readonly int GetHashCode()
		{
			int num = 0;
			if (Vector.IsHardwareAccelerated)
			{
				
				if (typeof(T) == typeof(int))
				{
					for (int n = 0; n < Vector<T>.Count; n++)
					{
						num = HashHelpers.Combine(num, ((int)((object)this[n])).GetHashCode());
					}
					return num;
				}
				
				if (typeof(T) == typeof(float))
				{
					for (int num4 = 0; num4 < Vector<T>.Count; num4++)
					{
						num = HashHelpers.Combine(num, ((float)((object)this[num4])).GetHashCode());
					}
					return num;
				}
				
				throw new NotSupportedException();
			}
			else
			{
				
				if (typeof(T) == typeof(int))
				{
					num = HashHelpers.Combine(num, this.register.int32_0.GetHashCode());
					num = HashHelpers.Combine(num, this.register.int32_1.GetHashCode());
					num = HashHelpers.Combine(num, this.register.int32_2.GetHashCode());
					return HashHelpers.Combine(num, this.register.int32_3.GetHashCode());
				}
				
				if (typeof(T) == typeof(float))
				{
					num = HashHelpers.Combine(num, this.register.single_0.GetHashCode());
					num = HashHelpers.Combine(num, this.register.single_1.GetHashCode());
					num = HashHelpers.Combine(num, this.register.single_2.GetHashCode());
					return HashHelpers.Combine(num, this.register.single_3.GetHashCode());
				}
				
				throw new NotSupportedException();
			}
		}

		
		public override readonly string ToString()
		{
			return this.ToString("G", CultureInfo.CurrentCulture);
		}

		
		public readonly string ToString(string format)
		{
			return this.ToString(format, CultureInfo.CurrentCulture);
		}

		public readonly string ToString(string format, IFormatProvider formatProvider)
		{
			StringBuilder stringBuilder = new StringBuilder();
			string numberGroupSeparator = NumberFormatInfo.GetInstance(formatProvider).NumberGroupSeparator;
			stringBuilder.Append('<');
			for (int i = 0; i < Vector<T>.Count - 1; i++)
			{
				stringBuilder.Append(((IFormattable)((object)this[i])).ToString(format, formatProvider));
				stringBuilder.Append(numberGroupSeparator);
				stringBuilder.Append(' ');
			}
			stringBuilder.Append(((IFormattable)((object)this[Vector<T>.Count - 1])).ToString(format, formatProvider));
			stringBuilder.Append('>');
			return stringBuilder.ToString();
		}

		public readonly bool TryCopyTo(Span<byte> destination)
		{
			//ThrowHelper.ThrowForUnsupportedVectorBaseType<T>();
			if (destination.Length < Vector<byte>.Count)
			{
				return false;
			}
			Unsafe.WriteUnaligned<Vector<T>>(ref MemoryMarshal.GetReference<byte>(destination), this);
			return true;
		}

		public readonly bool TryCopyTo(Span<T> destination)
		{
			if (destination.Length < Vector<T>.Count)
			{
				return false;
			}
			Unsafe.WriteUnaligned<Vector<T>>(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference<T>(destination)), this);
			return true;
		}

		
		public unsafe static Vector<T> operator +(Vector<T> left, Vector<T> right)
		{
			//if (!Vector.IsHardwareAccelerated)
			//{
				Vector<T> result = default;
				
				if (typeof(T) == typeof(int))
				{
					result.register.int32_0 = left.register.int32_0 + right.register.int32_0;
					result.register.int32_1 = left.register.int32_1 + right.register.int32_1;
					result.register.int32_2 = left.register.int32_2 + right.register.int32_2;
					result.register.int32_3 = left.register.int32_3 + right.register.int32_3;
				}
				
				else if (typeof(T) == typeof(float))
				{
					result.register.single_0 = left.register.single_0 + right.register.single_0;
					result.register.single_1 = left.register.single_1 + right.register.single_1;
					result.register.single_2 = left.register.single_2 + right.register.single_2;
					result.register.single_3 = left.register.single_3 + right.register.single_3;
				}
				
				return result;
			//}
			
			//if (typeof(T) == typeof(int))
			//{
			//	int* ptr6 = stackalloc int[checked(unchecked(Count * 4))];
			//	for (int n = 0; n < Vector<T>.Count; n++)
			//	{
			//		ptr6[n] = (int)((object)Vector<T>.ScalarAdd(left[n], right[n]));
			//	}
			//	return new Vector<T>((void*)ptr6);
			//}
			
			//if (typeof(T) == typeof(float))
			//{
			//	float* ptr9 = stackalloc float[checked(unchecked(Count * 4))];
			//	for (int num3 = 0; num3 < Vector<T>.Count; num3++)
			//	{
			//		ptr9[num3] = (float)((object)Vector<T>.ScalarAdd(left[num3], right[num3]));
			//	}
			//	return new Vector<T>((void*)ptr9);
			//}
			
			//throw new NotSupportedException();
		}

		
		public unsafe static Vector<T> operator -(Vector<T> left, Vector<T> right)
		{
			//if (!Vector.IsHardwareAccelerated)
			//{
				Vector<T> result = default;
				if (typeof(T) == typeof(int))
				{
					result.register.int32_0 = left.register.int32_0 - right.register.int32_0;
					result.register.int32_1 = left.register.int32_1 - right.register.int32_1;
					result.register.int32_2 = left.register.int32_2 - right.register.int32_2;
					result.register.int32_3 = left.register.int32_3 - right.register.int32_3;
				}
				
				else if (typeof(T) == typeof(float))
				{
					result.register.single_0 = left.register.single_0 - right.register.single_0;
					result.register.single_1 = left.register.single_1 - right.register.single_1;
					result.register.single_2 = left.register.single_2 - right.register.single_2;
					result.register.single_3 = left.register.single_3 - right.register.single_3;
				}
				
				return result;
			//}
			
			//if (typeof(T) == typeof(int))
			//{
			//	int* ptr6 = stackalloc int[checked(unchecked(Count * 4))];
			//	for (int n = 0; n < Vector<T>.Count; n++)
			//	{
			//		ptr6[n] = (int)((object)Vector<T>.ScalarSubtract(left[n], right[n]));
			//	}
			//	return new Vector<T>((void*)ptr6);
			//}
			//if (typeof(T) == typeof(float))
			//{
			//	float* ptr9 = stackalloc float[checked(unchecked(Count * 4))];
			//	for (int num3 = 0; num3 < Vector<T>.Count; num3++)
			//	{
			//		ptr9[num3] = (float)((object)Vector<T>.ScalarSubtract(left[num3], right[num3]));
			//	}
			//	return new Vector<T>((void*)ptr9);
			//}
			//throw new NotSupportedException();
		}

		
		public unsafe static Vector<T> operator *(Vector<T> left, Vector<T> right)
		{
			//if (!Vector.IsHardwareAccelerated)
			//{
				Vector<T> result = default;
				if (typeof(T) == typeof(int))
				{
					result.register.int32_0 = left.register.int32_0 * right.register.int32_0;
					result.register.int32_1 = left.register.int32_1 * right.register.int32_1;
					result.register.int32_2 = left.register.int32_2 * right.register.int32_2;
					result.register.int32_3 = left.register.int32_3 * right.register.int32_3;
				}
				
				else if (typeof(T) == typeof(float))
				{
					result.register.single_0 = left.register.single_0 * right.register.single_0;
					result.register.single_1 = left.register.single_1 * right.register.single_1;
					result.register.single_2 = left.register.single_2 * right.register.single_2;
					result.register.single_3 = left.register.single_3 * right.register.single_3;
				}
				
				return result;
			//}
			
			//if (typeof(T) == typeof(int))
			//{
			//	int* ptr6 = stackalloc int[checked(unchecked(Count * 4))];
			//	for (int n = 0; n < Count; n++)
			//	{
			//		ptr6[n] = (int)((object)ScalarMultiply(left[n], right[n]));
			//	}
			//	return new Vector<T>(ptr6);
			//}
			
			//if (typeof(T) == typeof(float))
			//{
			//	float* ptr9 = stackalloc float[checked(unchecked(Count * 4))];
			//	for (int num3 = 0; num3 < Count; num3++)
			//	{
			//		ptr9[num3] = (float)(object)ScalarMultiply(left[num3], right[num3]);
			//	}
			//	return new Vector<T>(ptr9);
			//}
			
			throw new NotSupportedException();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Vector<T> operator *(Vector<T> value, T factor)
		{
			return new Vector<T>(factor) * value;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Vector<T> operator *(T factor, Vector<T> value)
		{
			return new Vector<T>(factor) * value;
		}

		
		public unsafe static Vector<T> operator /(Vector<T> left, Vector<T> right)
		{
			//if (!Vector.IsHardwareAccelerated)
			//{
				Vector<T> result = default;
				if (typeof(T) == typeof(int))
				{
					result.register.int32_0 = left.register.int32_0 / right.register.int32_0;
					result.register.int32_1 = left.register.int32_1 / right.register.int32_1;
					result.register.int32_2 = left.register.int32_2 / right.register.int32_2;
					result.register.int32_3 = left.register.int32_3 / right.register.int32_3;
				}
				
				else if (typeof(T) == typeof(float))
				{
					result.register.single_0 = left.register.single_0 / right.register.single_0;
					result.register.single_1 = left.register.single_1 / right.register.single_1;
					result.register.single_2 = left.register.single_2 / right.register.single_2;
					result.register.single_3 = left.register.single_3 / right.register.single_3;
				}
				
				return result;
			//}
			
			//if (typeof(T) == typeof(int))
			//{
			//	int* ptr6 = stackalloc int[checked(unchecked(Count * 4))];
			//	for (int n = 0; n < Vector<T>.Count; n++)
			//	{
			//		ptr6[n] = (int)((object)Vector<T>.ScalarDivide(left[n], right[n]));
			//	}
			//	return new Vector<T>((void*)ptr6);
			//}
			
			//if (typeof(T) == typeof(float))
			//{
			//	float* ptr9 = stackalloc float[checked(unchecked(Count * 4))];
			//	for (int num3 = 0; num3 < Vector<T>.Count; num3++)
			//	{
			//		ptr9[num3] = (float)((object)Vector<T>.ScalarDivide(left[num3], right[num3]));
			//	}
			//	return new Vector<T>((void*)ptr9);
			//}
			
			//throw new NotSupportedException();
		}

		public static Vector<T> operator -(Vector<T> value)
		{
			return Vector<T>.Zero - value;
		}

		
		public unsafe static Vector<T> operator &(Vector<T> left, Vector<T> right)
		{
			Vector<T> result = default;
			if (Vector.IsHardwareAccelerated)
			{
				long* ptr = &result.register.int64_0;
				long* ptr2 = &left.register.int64_0;
				long* ptr3 = &right.register.int64_0;
				for (int i = 0; i < Vector<long>.Count; i++)
				{
					ptr[i] = (ptr2[i] & ptr3[i]);
				}
			}
			else
			{
				result.register.int64_0 = (left.register.int64_0 & right.register.int64_0);
				result.register.int64_1 = (left.register.int64_1 & right.register.int64_1);
			}
			return result;
		}

		
		public unsafe static Vector<T> operator |(Vector<T> left, Vector<T> right)
		{
			Vector<T> result = default(Vector<T>);
			if (Vector.IsHardwareAccelerated)
			{
				long* ptr = &result.register.int64_0;
				long* ptr2 = &left.register.int64_0;
				long* ptr3 = &right.register.int64_0;
				for (int i = 0; i < Vector<long>.Count; i++)
				{
					ptr[i] = (ptr2[i] | ptr3[i]);
				}
			}
			else
			{
				result.register.int64_0 = (left.register.int64_0 | right.register.int64_0);
				result.register.int64_1 = (left.register.int64_1 | right.register.int64_1);
			}
			return result;
		}

		
		public unsafe static Vector<T> operator ^(Vector<T> left, Vector<T> right)
		{
			Vector<T> result = default(Vector<T>);
			if (Vector.IsHardwareAccelerated)
			{
				long* ptr = &result.register.int64_0;
				long* ptr2 = &left.register.int64_0;
				long* ptr3 = &right.register.int64_0;
				for (int i = 0; i < Vector<long>.Count; i++)
				{
					ptr[i] = (ptr2[i] ^ ptr3[i]);
				}
			}
			else
			{
				result.register.int64_0 = (left.register.int64_0 ^ right.register.int64_0);
				result.register.int64_1 = (left.register.int64_1 ^ right.register.int64_1);
			}
			return result;
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Vector<T> operator ~(Vector<T> value)
		{
			return Vector<T>.s_allOnes ^ value;
		}

		
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool operator ==(Vector<T> left, Vector<T> right)
		{
			return left.Equals(right);
		}

		
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static bool operator !=(Vector<T> left, Vector<T> right)
		{
			return !(left == right);
		}

		
		public static explicit operator Vector<byte>(Vector<T> value)
		{
			return new Vector<byte>(ref value.register);
		}

		
		[CLSCompliant(false)]
		public static explicit operator Vector<sbyte>(Vector<T> value)
		{
			return new Vector<sbyte>(ref value.register);
		}

		[CLSCompliant(false)]
		
		public static explicit operator Vector<ushort>(Vector<T> value)
		{
			return new Vector<ushort>(ref value.register);
		}

		
		public static explicit operator Vector<short>(Vector<T> value)
		{
			return new Vector<short>(ref value.register);
		}

		[CLSCompliant(false)]
		
		public static explicit operator Vector<uint>(Vector<T> value)
		{
			return new Vector<uint>(ref value.register);
		}

		
		public static explicit operator Vector<int>(Vector<T> value)
		{
			return new Vector<int>(ref value.register);
		}

		
		[CLSCompliant(false)]
		public static explicit operator Vector<ulong>(Vector<T> value)
		{
			return new Vector<ulong>(ref value.register);
		}

		
		public static explicit operator Vector<long>(Vector<T> value)
		{
			return new Vector<long>(ref value.register);
		}

		
		public static explicit operator Vector<float>(Vector<T> value)
		{
			return new Vector<float>(ref value.register);
		}

		
		public static explicit operator Vector<double>(Vector<T> value)
		{
			return new Vector<double>(ref value.register);
		}

		
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal unsafe static Vector<T> Equals(Vector<T> left, Vector<T> right)
		{
			if (Vector.IsHardwareAccelerated)
			{
				if (typeof(T) == typeof(int))
				{
					int* ptr6 = stackalloc int[checked(unchecked(Count * 4))];
					for (int n = 0; n < Vector<T>.Count; n++)
					{
						ptr6[n] = (Vector<T>.ScalarEquals(left[n], right[n]) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					}
					return new Vector<T>((void*)ptr6);
				}
				
				if (typeof(T) == typeof(float))
				{
					float* ptr9 = stackalloc float[checked(unchecked(Count * 4))];
					for (int num3 = 0; num3 < Vector<T>.Count; num3++)
					{
						ptr9[num3] = (Vector<T>.ScalarEquals(left[num3], right[num3]) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					}
					return new Vector<T>((void*)ptr9);
				}
				
				throw new NotSupportedException();
			}
			else
			{
				Register register = default(Register);
				
				if (typeof(T) == typeof(int))
				{
					register.int32_0 = ((left.register.int32_0 == right.register.int32_0) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					register.int32_1 = ((left.register.int32_1 == right.register.int32_1) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					register.int32_2 = ((left.register.int32_2 == right.register.int32_2) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					register.int32_3 = ((left.register.int32_3 == right.register.int32_3) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					return new Vector<T>(ref register);
				}
				
				if (typeof(T) == typeof(float))
				{
					register.single_0 = ((left.register.single_0 == right.register.single_0) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					register.single_1 = ((left.register.single_1 == right.register.single_1) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					register.single_2 = ((left.register.single_2 == right.register.single_2) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					register.single_3 = ((left.register.single_3 == right.register.single_3) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					return new Vector<T>(ref register);
				}
				
				throw new NotSupportedException();
			}
		}

		
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal unsafe static Vector<T> LessThan(Vector<T> left, Vector<T> right)
		{
			if (Vector.IsHardwareAccelerated)
			{
				
				if (typeof(T) == typeof(int))
				{
					int* ptr6 = stackalloc int[checked(unchecked(Count * 4))];
					for (int n = 0; n < Vector<T>.Count; n++)
					{
						ptr6[n] = (Vector<T>.ScalarLessThan(left[n], right[n]) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					}
					return new Vector<T>((void*)ptr6);
				}
				
				if (typeof(T) == typeof(float))
				{
					float* ptr9 = stackalloc float[checked(unchecked(Count * 4))];
					for (int num3 = 0; num3 < Vector<T>.Count; num3++)
					{
						ptr9[num3] = (Vector<T>.ScalarLessThan(left[num3], right[num3]) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					}
					return new Vector<T>((void*)ptr9);
				}
				
				throw new NotSupportedException();
			}
			else
			{
				Register register = default(Register);
				
				if (typeof(T) == typeof(int))
				{
					register.int32_0 = ((left.register.int32_0 < right.register.int32_0) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					register.int32_1 = ((left.register.int32_1 < right.register.int32_1) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					register.int32_2 = ((left.register.int32_2 < right.register.int32_2) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					register.int32_3 = ((left.register.int32_3 < right.register.int32_3) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					return new Vector<T>(ref register);
				}
				
				if (typeof(T) == typeof(float))
				{
					register.single_0 = ((left.register.single_0 < right.register.single_0) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					register.single_1 = ((left.register.single_1 < right.register.single_1) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					register.single_2 = ((left.register.single_2 < right.register.single_2) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					register.single_3 = ((left.register.single_3 < right.register.single_3) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					return new Vector<T>(ref register);
				}
				
				throw new NotSupportedException();
			}
		}

		
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		internal unsafe static Vector<T> GreaterThan(Vector<T> left, Vector<T> right)
		{
			if (Vector.IsHardwareAccelerated)
			{
				
				if (typeof(T) == typeof(int))
				{
					int* ptr6 = stackalloc int[checked(unchecked(Count * 4))];
					for (int n = 0; n < Vector<T>.Count; n++)
					{
						ptr6[n] = (Vector<T>.ScalarGreaterThan(left[n], right[n]) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					}
					return new Vector<T>((void*)ptr6);
				}
				
				if (typeof(T) == typeof(float))
				{
					float* ptr9 = stackalloc float[checked(unchecked(Count * 4))];
					for (int num3 = 0; num3 < Vector<T>.Count; num3++)
					{
						ptr9[num3] = (Vector<T>.ScalarGreaterThan(left[num3], right[num3]) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					}
					return new Vector<T>((void*)ptr9);
				}
				
				throw new NotSupportedException();
			}
			else
			{
				Register register = default(Register);
				
				if (typeof(T) == typeof(int))
				{
					register.int32_0 = ((left.register.int32_0 > right.register.int32_0) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					register.int32_1 = ((left.register.int32_1 > right.register.int32_1) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					register.int32_2 = ((left.register.int32_2 > right.register.int32_2) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					register.int32_3 = ((left.register.int32_3 > right.register.int32_3) ? ConstantHelper.GetInt32WithAllBitsSet() : 0);
					return new Vector<T>(ref register);
				}
				
				if (typeof(T) == typeof(float))
				{
					register.single_0 = ((left.register.single_0 > right.register.single_0) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					register.single_1 = ((left.register.single_1 > right.register.single_1) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					register.single_2 = ((left.register.single_2 > right.register.single_2) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					register.single_3 = ((left.register.single_3 > right.register.single_3) ? ConstantHelper.GetSingleWithAllBitsSet() : 0f);
					return new Vector<T>(ref register);
				}
				
				throw new NotSupportedException();
			}
		}

		
		internal static Vector<T> GreaterThanOrEqual(Vector<T> left, Vector<T> right)
		{
			return Vector<T>.Equals(left, right) | Vector<T>.GreaterThan(left, right);
		}

		
		internal static Vector<T> LessThanOrEqual(Vector<T> left, Vector<T> right)
		{
			return Vector<T>.Equals(left, right) | Vector<T>.LessThan(left, right);
		}

		
		internal static Vector<T> ConditionalSelect(Vector<T> condition, Vector<T> left, Vector<T> right)
		{
			return (left & condition) | Vector.AndNot<T>(right, condition);
		}

		
		internal unsafe static Vector<T> Abs(Vector<T> value)
		{
			if (typeof(T) == typeof(byte))
			{
				return value;
			}
			if (typeof(T) == typeof(ushort))
			{
				return value;
			}
			if (typeof(T) == typeof(uint))
			{
				return value;
			}
			if (typeof(T) == typeof(ulong))
			{
				return value;
			}
			if (Vector.IsHardwareAccelerated)
			{
				
				if (typeof(T) == typeof(int))
				{
					int* ptr3 = stackalloc int[checked(unchecked(Count * 4))];
					for (int k = 0; k < Vector<T>.Count; k++)
					{
						ptr3[k] = (int)Math.Abs((int)((object)value[k]));
					}
					return new Vector<T>((void*)ptr3);
				}
				
				if (typeof(T) == typeof(float))
				{
					float* ptr5 = stackalloc float[checked(unchecked(Count * 4))];
					for (int m = 0; m < Vector<T>.Count; m++)
					{
						ptr5[m] = (float)Math.Abs((float)((object)value[m]));
					}
					return new Vector<T>((void*)ptr5);
				}
				
				throw new NotSupportedException();
			}
			else
			{
				
				if (typeof(T) == typeof(int))
				{
					value.register.int32_0 = Math.Abs(value.register.int32_0);
					value.register.int32_1 = Math.Abs(value.register.int32_1);
					value.register.int32_2 = Math.Abs(value.register.int32_2);
					value.register.int32_3 = Math.Abs(value.register.int32_3);
					return value;
				}
				
				if (typeof(T) == typeof(float))
				{
					value.register.single_0 = Math.Abs(value.register.single_0);
					value.register.single_1 = Math.Abs(value.register.single_1);
					value.register.single_2 = Math.Abs(value.register.single_2);
					value.register.single_3 = Math.Abs(value.register.single_3);
					return value;
				}
				throw new NotSupportedException();
			}
		}

		
		internal unsafe static Vector<T> Min(Vector<T> left, Vector<T> right)
		{
			if (Vector.IsHardwareAccelerated)
			{
				
				if (typeof(T) == typeof(int))
				{
					int* ptr6 = stackalloc int[checked(unchecked(Count * 4))];
					for (int n = 0; n < Vector<T>.Count; n++)
					{
						ptr6[n] = (Vector<T>.ScalarLessThan(left[n], right[n]) ? ((int)((object)left[n])) : ((int)((object)right[n])));
					}
					return new Vector<T>((void*)ptr6);
				}
				
				if (typeof(T) == typeof(float))
				{
					float* ptr9 = stackalloc float[checked(unchecked(Count * 4))];
					for (int num3 = 0; num3 < Vector<T>.Count; num3++)
					{
						ptr9[num3] = (Vector<T>.ScalarLessThan(left[num3], right[num3]) ? ((float)((object)left[num3])) : ((float)((object)right[num3])));
					}
					return new Vector<T>((void*)ptr9);
				}
				throw new NotSupportedException();
			}
			else
			{
				Vector<T> result = default(Vector<T>);
				
				if (typeof(T) == typeof(int))
				{
					result.register.int32_0 = ((left.register.int32_0 < right.register.int32_0) ? left.register.int32_0 : right.register.int32_0);
					result.register.int32_1 = ((left.register.int32_1 < right.register.int32_1) ? left.register.int32_1 : right.register.int32_1);
					result.register.int32_2 = ((left.register.int32_2 < right.register.int32_2) ? left.register.int32_2 : right.register.int32_2);
					result.register.int32_3 = ((left.register.int32_3 < right.register.int32_3) ? left.register.int32_3 : right.register.int32_3);
					return result;
				}
				
				if (typeof(T) == typeof(float))
				{
					result.register.single_0 = ((left.register.single_0 < right.register.single_0) ? left.register.single_0 : right.register.single_0);
					result.register.single_1 = ((left.register.single_1 < right.register.single_1) ? left.register.single_1 : right.register.single_1);
					result.register.single_2 = ((left.register.single_2 < right.register.single_2) ? left.register.single_2 : right.register.single_2);
					result.register.single_3 = ((left.register.single_3 < right.register.single_3) ? left.register.single_3 : right.register.single_3);
					return result;
				}
				throw new NotSupportedException();
			}
		}

		
		internal unsafe static Vector<T> Max(Vector<T> left, Vector<T> right)
		{
			if (Vector.IsHardwareAccelerated)
			{
				
				if (typeof(T) == typeof(int))
				{
					int* ptr6 = stackalloc int[checked(unchecked(Count * 4))];
					for (int n = 0; n < Vector<T>.Count; n++)
					{
						ptr6[n] = (Vector<T>.ScalarGreaterThan(left[n], right[n]) ? ((int)((object)left[n])) : ((int)((object)right[n])));
					}
					return new Vector<T>((void*)ptr6);
				}
				
				if (typeof(T) == typeof(float))
				{
					float* ptr9 = stackalloc float[checked(unchecked(Count * 4))];
					for (int num3 = 0; num3 < Vector<T>.Count; num3++)
					{
						ptr9[num3] = (Vector<T>.ScalarGreaterThan(left[num3], right[num3]) ? ((float)((object)left[num3])) : ((float)((object)right[num3])));
					}
					return new Vector<T>((void*)ptr9);
				}
				
				throw new NotSupportedException();
			}
			else
			{
				Vector<T> result = default(Vector<T>);
				
				if (typeof(T) == typeof(int))
				{
					result.register.int32_0 = ((left.register.int32_0 > right.register.int32_0) ? left.register.int32_0 : right.register.int32_0);
					result.register.int32_1 = ((left.register.int32_1 > right.register.int32_1) ? left.register.int32_1 : right.register.int32_1);
					result.register.int32_2 = ((left.register.int32_2 > right.register.int32_2) ? left.register.int32_2 : right.register.int32_2);
					result.register.int32_3 = ((left.register.int32_3 > right.register.int32_3) ? left.register.int32_3 : right.register.int32_3);
					return result;
				}
				
				if (typeof(T) == typeof(float))
				{
					result.register.single_0 = ((left.register.single_0 > right.register.single_0) ? left.register.single_0 : right.register.single_0);
					result.register.single_1 = ((left.register.single_1 > right.register.single_1) ? left.register.single_1 : right.register.single_1);
					result.register.single_2 = ((left.register.single_2 > right.register.single_2) ? left.register.single_2 : right.register.single_2);
					result.register.single_3 = ((left.register.single_3 > right.register.single_3) ? left.register.single_3 : right.register.single_3);
					return result;
				}
				throw new NotSupportedException();
			}
		}

		
		internal static T Dot(Vector<T> left, Vector<T> right)
		{
			if (Vector.IsHardwareAccelerated)
			{
				T t = default(T);
				for (int i = 0; i < Vector<T>.Count; i++)
				{
					t = Vector<T>.ScalarAdd(t, Vector<T>.ScalarMultiply(left[i], right[i]));
				}
				return t;
			}
			
			if (typeof(T) == typeof(int))
			{
				int num4 = 0;
				num4 += left.register.int32_0 * right.register.int32_0;
				num4 += left.register.int32_1 * right.register.int32_1;
				num4 += left.register.int32_2 * right.register.int32_2;
				num4 += left.register.int32_3 * right.register.int32_3;
				return (T)((object)num4);
			}
			
			if (typeof(T) == typeof(float))
			{
				float num7 = 0f;
				num7 += left.register.single_0 * right.register.single_0;
				num7 += left.register.single_1 * right.register.single_1;
				num7 += left.register.single_2 * right.register.single_2;
				num7 += left.register.single_3 * right.register.single_3;
				return (T)((object)num7);
			}
			throw new NotSupportedException();
		}

		
		internal unsafe static Vector<T> SquareRoot(Vector<T> value)
		{
			if (Vector.IsHardwareAccelerated)
			{
				
				if (typeof(T) == typeof(int))
				{
					int* ptr6 = stackalloc int[checked(unchecked(Count * 4))];
					for (int n = 0; n < Vector<T>.Count; n++)
					{
						ptr6[n] = (int)Math.Sqrt((double)((int)((object)value[n])));
					}
					return new Vector<T>((void*)ptr6);
				}
				
				if (typeof(T) == typeof(float))
				{
					float* ptr9 = stackalloc float[checked(unchecked(Count * 4))];
					for (int num3 = 0; num3 < Vector<T>.Count; num3++)
					{
						ptr9[num3] = (float)Math.Sqrt((double)((float)((object)value[num3])));
					}
					return new Vector<T>((void*)ptr9);
				}
				
				throw new NotSupportedException();
			}
			else
			{
				
				if (typeof(T) == typeof(int))
				{
					value.register.int32_0 = (int)Math.Sqrt((double)value.register.int32_0);
					value.register.int32_1 = (int)Math.Sqrt((double)value.register.int32_1);
					value.register.int32_2 = (int)Math.Sqrt((double)value.register.int32_2);
					value.register.int32_3 = (int)Math.Sqrt((double)value.register.int32_3);
					return value;
				}
				
				if (typeof(T) == typeof(float))
				{
					value.register.single_0 = (float)Math.Sqrt((double)value.register.single_0);
					value.register.single_1 = (float)Math.Sqrt((double)value.register.single_1);
					value.register.single_2 = (float)Math.Sqrt((double)value.register.single_2);
					value.register.single_3 = (float)Math.Sqrt((double)value.register.single_3);
					return value;
				}
				throw new NotSupportedException();
			}
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static bool ScalarEquals(T left, T right)
		{
			
			if (typeof(T) == typeof(int))
			{
				return (int)((object)left) == (int)((object)right);
			}
			
			if (typeof(T) == typeof(float))
			{
				return (float)((object)left) == (float)((object)right);
			}
			
			throw new NotSupportedException();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static bool ScalarLessThan(T left, T right)
		{
			
			if (typeof(T) == typeof(int))
			{
				return (int)((object)left) < (int)((object)right);
			}
			
			if (typeof(T) == typeof(float))
			{
				return (float)((object)left) < (float)((object)right);
			}
			throw new NotSupportedException();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static bool ScalarGreaterThan(T left, T right)
		{
			
			if (typeof(T) == typeof(int))
			{
				return (int)((object)left) > (int)((object)right);
			}
			
			if (typeof(T) == typeof(float))
			{
				return (float)((object)left) > (float)((object)right);
			}
			
			throw new NotSupportedException();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static T ScalarAdd(T left, T right)
		{
			
			if (typeof(T) == typeof(int))
			{
				return (T)((object)((int)((object)left) + (int)((object)right)));
			}
			
			if (typeof(T) == typeof(float))
			{
				return (T)((object)((float)((object)left) + (float)((object)right)));
			}
			
			throw new NotSupportedException();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static T ScalarSubtract(T left, T right)
		{
			
			if (typeof(T) == typeof(int))
			{
				return (T)((object)((int)((object)left) - (int)((object)right)));
			}
			
			if (typeof(T) == typeof(float))
			{
				return (T)((object)((float)((object)left) - (float)((object)right)));
			}
			
			throw new NotSupportedException();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static T ScalarMultiply(T left, T right)
		{
			
			if (typeof(T) == typeof(int))
			{
				return (T)((object)((int)((object)left) * (int)((object)right)));
			}
			
			if (typeof(T) == typeof(float))
			{
				return (T)(object)((float)(object)left * (float)(object)right);
			}
			
			throw new NotSupportedException();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static T ScalarDivide(T left, T right)
		{
			
			if (typeof(T) == typeof(int))
			{
				return (T)((object)((int)((object)left) / (int)((object)right)));
			}
			
			if (typeof(T) == typeof(float))
			{
				return (T)((object)((float)((object)left) / (float)((object)right)));
			}
			
			throw new NotSupportedException();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static T GetOneValue()
		{
			
			if (typeof(T) == typeof(int))
			{
				int num4 = 1;
				return (T)((object)num4);
			}
			
			if (typeof(T) == typeof(float))
			{
				float num7 = 1f;
				return (T)((object)num7);
			}
			
			throw new NotSupportedException();
		}

		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		private static T GetAllBitsSetValue()
		{
			
			if (typeof(T) == typeof(int))
			{
				return (T)((object)ConstantHelper.GetInt32WithAllBitsSet());
			}
			
			if (typeof(T) == typeof(float))
			{
				return (T)((object)ConstantHelper.GetSingleWithAllBitsSet());
			}
			
			throw new NotSupportedException();
		}

		private Register register;

		private static readonly Vector<T> s_zero = default(Vector<T>);

		private static readonly Vector<T> s_one = new Vector<T>(Vector<T>.GetOneValue());

		private static readonly Vector<T> s_allOnes = new Vector<T>(Vector<T>.GetAllBitsSetValue());
	}
}